package de.unibi.comet.util;

/** Helps with calculations in logarithmic domain. */
public class LogSpace {
	
	/** Given log x and log y, returns log (x+y) */
	public static double logAdd(double logX, double logY) {
		if (Double.isNaN(logX) || Double.isNaN(logY)) return Double.NaN;
		// possibly swap to ensure x>y
		if (logY > logX) {
			double temp = logX;
			logX = logY;
			logY = temp;
		}
		// if both are -inf, just return -inf
		if (logX==Double.NEGATIVE_INFINITY) return Double.NEGATIVE_INFINITY;
		
		// otherwise use log1p to compute result
		return logX + Math.log1p(Math.exp(logY-logX));
	}

	/** Given log x and log y, returns log (x-y) */
	public static double logSub(double logX, double logY) {
		if (Double.isNaN(logX) || Double.isNaN(logY)) return Double.NaN;
		if (logY > logX) return Double.NaN;
		// if both are -inf, just return -inf
		if (Double.isInfinite(logX) && (logX<0.0)) return Double.NEGATIVE_INFINITY;
		
		// otherwise use log1p to compute result
		return logX + Math.log1p(-Math.exp(logY-logX));
	}
	
	public static String toString(double d) {
		if (Double.isNaN(d)) return String.valueOf(d);
		d/=Math.log(10.0);
		double exp;
		double factor;
		if (d<0.0) {
			exp=-Math.ceil(-d);
			factor=d-exp;
		} else {
			exp=Math.floor(d);
			factor=d-exp;
		}
		return String.format("%.6fe%+d", Math.exp(factor*Math.log(10.0)), (int)exp);
	}
}
